/*
 * comm_objbase.c
 *
 *  Created on: 2010-1-7
 *      Author: gavinkwoe
 */

#include "comm_features.h"

#if (__COMM_TARGET__ == __TARGET_SYMBIAN)

#include "comm_std.h"
#include "comm_mem.h"
#include "comm_objbase.h"

/*************************************************************************
* GUID
*************************************************************************/

COMM_DEFINED_GUID( ICommO, 1, "" )

/*************************************************************************
* PROTOTYPE
*************************************************************************/

struct __struct_comm_obj_layout;
typedef struct __struct_comm_obj_layout	comm_obj_layout_t;
typedef struct __struct_comm_obj_layout *	comm_obj_layout_ptr_t;

/*************************************************************************
* STRUCTURE
*************************************************************************/

//////////////////////////////////////////
//  ---------------------
//  | object header     | -> object header
//  ---------------------
//  | vtbl_ptr          | -> virtual table
//  ---------------------
//  | priv_data         | -> member data
//  ---------------------
//////////////////////////////////////////
struct __struct_comm_obj_layout
{
	unsigned char *	v_table;
	unsigned char	p_data[1];
};

/*************************************************************************
* LOCAL FUNCTIONS
*************************************************************************/

unsigned long	__construct( comm_obj_layout_ptr_t obj_ptr, void * usr_data );
static void				__destruct( comm_obj_layout_ptr_t obj_ptr );

/*************************************************************************
* IMPLEMENTATION
*************************************************************************/

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
unsigned long __construct( comm_obj_layout_ptr_t obj_ptr, void * usr_data )
{
	unsigned long ret_val;
	COMM_VTBL(ICommO)	vtbl_ptr = ( COMM_VTBL(ICommO) )obj_ptr->v_table;

	if ( NULL == vtbl_ptr )
		return COMM_FALSE;

	if ( NULL == vtbl_ptr->Construct )
		return COMM_TRUE;

	ret_val = COMM_INVOKE( vtbl_ptr->Construct, ((COMM_REF(ICommO))obj_ptr, usr_data) );
	return ( COMM_FAILED != ret_val ? COMM_TRUE : COMM_FALSE );
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
static void __destruct( comm_obj_layout_ptr_t obj_ptr )
{
	COMM_VTBL(ICommO) vtbl_ptr = ( COMM_VTBL(ICommO) )obj_ptr->v_table;
	
	if ( NULL == vtbl_ptr )
		return;

	if ( NULL == vtbl_ptr->Destruct )
		return;

	COMM_INVOKE( vtbl_ptr->Destruct, ((COMM_REF(ICommO))obj_ptr) );
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void * comm_obj_new( comm_coclass_desc_ptr_t desc, void * usr_data )
{
	unsigned long			ret_val = COMM_FALSE;
	unsigned long			obj_size = 0;
	comm_obj_layout_ptr_t	obj_ptr = NULL;

	if ( NULL == desc || NULL == desc->vtbl_funcs )
		return NULL;

	obj_size = sizeof(comm_obj_layout_t) + desc->priv_size;
	obj_ptr = (comm_obj_layout_ptr_t)COMM_HEAP_ALLOC( obj_size );
	if ( NULL == obj_ptr )
		return NULL;

#if defined(__COPY_VTBALE__)
	obj_ptr->v_table = (unsigned char *)COMM_HEAP_ALLOC( desc->vtbl_size );
	if ( NULL == obj_ptr->v_table )
		goto __FAILED;

	COMM_MEMCPY( obj_ptr->v_table, desc->vtbl_funcs, desc->vtbl_size );
#else	// #if defined(__COPY_VTBALE__)
	obj_ptr->v_table = desc->vtbl_funcs;
#endif	// __COPY_VTBALE__

	ret_val = __construct( obj_ptr, usr_data );
	if ( COMM_FALSE == ret_val )
		goto __FAILED;

	return (void *)obj_ptr;

__FAILED:
	if ( NULL != obj_ptr )
	{
	#if defined(__COPY_VTBALE__)
		COMM_HEAP_FREE( obj_ptr->v_table );
	#endif	// #if defined(__COPY_VTBALE__)
		COMM_HEAP_FREE( obj_ptr );
	}
	return NULL;
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
COMM_EXPORT void comm_obj_delete( void * thiz )
{
	comm_obj_layout_ptr_t obj_ptr = (comm_obj_layout_ptr_t)thiz;
	if ( NULL != obj_ptr )
	{
		__destruct( obj_ptr );
	#if defined(__COPY_VTBALE__)
		COMM_HEAP_FREE( obj_ptr->v_table );
	#endif	// #if defined(__COPY_VTBALE__)
		COMM_HEAP_FREE( obj_ptr );
	}
}

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
#ifndef __COMM_FAST_OBJECT_ACCESS__
unsigned char * comm_obj_get_data( void * thiz )
{
	comm_obj_layout_ptr_t obj_ptr = (comm_obj_layout_ptr_t)thiz;
	return ( NULL == obj_ptr ? NULL : &obj_ptr->p_data[0] );
}
#endif	// #ifndef __COMM_FAST_OBJECT_ACCESS__

/*************************************************************************
* DESCRIPTION
*	$$__FUNC_DESC__$$
*************************************************************************/
#ifndef __COMM_FAST_OBJECT_ACCESS__
void * comm_obj_get_vptr( void * thiz )
{
	comm_obj_layout_ptr_t obj_ptr = (comm_obj_layout_ptr_t)thiz;
	return ( NULL == obj_ptr ? NULL : obj_ptr->v_table );
}
#endif	// #ifndef __COMM_FAST_OBJECT_ACCESS__

#endif	// #if (__COMM_TARGET__ == __TARGET_SYMBIAN)
